package com.lanyou.cook.web;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.map.MultiKeyMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.lanyou.cook.common.Constants;
import com.lanyou.cook.datadictionary.InterfaceRunResult;
import com.lanyou.cook.entity.domain.InterfaceExecutionResult;
import com.lanyou.cook.entity.domain.ParamSetting;
import com.lanyou.cook.repository.InterfaceExecutionResultRepository;
import com.lanyou.cook.repository.ParamSettingRepository;
import com.lanyou.cook.service.security.UserSessionService;
import com.lanyou.cook.util.DateUtil;
import com.lanyou.cook.web.param.InterfaceExecutionResultParam;
/**
 * 
 * @author 曾族根
 *
 */
@RestController
@RequestMapping(Constants.BASE_URL_API + "/interfaceExecutionResults")
public class InterfaceExecutionResultController {
	@Autowired
	UserSessionService userSessionService;
	@Autowired
	ParamSettingRepository  paramSettingRepository;
	@PersistenceContext
	private EntityManager entityManager;
	@Autowired
	private InterfaceExecutionResultRepository interfaceExecutionResultRepository;
	/**
	 * 查询领域作业历史信息
	 * @param param 类型: InterfaceExecutionResultParam
	 * @param pageable: Pageable
	 * @return 带参数条件的所有作业信息
	 */
	@RequestMapping("/search/findByExample")
	@RequiresPermissions(value={"historyInterfaceImplementationQuery","interfaceSchedulingHistoryQuery:view","failuredWarningInfoReport:view","implementationInterfaceQuery:view"}, logical=Logical.OR)
	public Page<InterfaceExecutionResult> findByExample(InterfaceExecutionResultParam param, Pageable pageable) {

		Specification<InterfaceExecutionResult> spec = new Specification<InterfaceExecutionResult>() {
			@Override
			public Predicate toPredicate(Root<InterfaceExecutionResult> root, CriteriaQuery<?> query,
					CriteriaBuilder cb) {
				List<Predicate> predicatesList = new ArrayList<>();

				if (StringUtils.isNotBlank(param.getInterfaceName())) {
					predicatesList.add(cb.like(root.get("interfaceName"), '%' + param.getInterfaceName() + "%"));
				}
				if (StringUtils.isNoneBlank(param.getFieldName())) {
					predicatesList.add(cb.equal(root.get("fieldName"), param.getFieldName()));
				}
				if (StringUtils.isNoneBlank(param.getFieldSystemName())) {
					predicatesList.add(cb.equal(root.get("fieldSystemName"), param.getFieldSystemName()));
				}else{
					Path<String> pathOwnerFieldSystemId = root.get("fieldSystemId");
					// 默认查当前登录用户所管理的领域系统
					Collection<String> fieldSystemIds = userSessionService.findFieldSystemIdsOfCurrentAuthenticatedUserCanManage();
					if(!CollectionUtils.isEmpty(fieldSystemIds)){
						predicatesList.add(pathOwnerFieldSystemId.in(fieldSystemIds));
					}else {
						predicatesList.add(cb.notEqual(cb.literal(1), 1));
					}
				}
				if (StringUtils.isNotBlank(param.getResult())) {
					predicatesList.add(cb.equal(root.get("runResult"), param.getResult()));
				}
				if (StringUtils.isNotBlank(param.getSkdResult())) {
					predicatesList.add(cb.equal(root.get("skdResult"), param.getSkdResult()));
				}
				if (StringUtils.isNotBlank(param.getScheduleName())) {	
					predicatesList.add(cb.equal(root.get("scheduleName"), param.getScheduleName()));
				}
				if (StringUtils.isNotBlank(param.getScheduleName1())) {
					predicatesList.add(cb.like(root.get("scheduleName"), "%" + param.getScheduleName1() + "%"));
				}
				if(StringUtils.isNotBlank(param.getQuantity())){
					if(StringUtils.equalsIgnoreCase(param.getQuantity(), "一致")){
					predicatesList.add(cb.equal(root.get("recordQTY"), root.get("inputQTY")));
					}else{
						predicatesList.add(cb.notEqual(root.get("recordQTY"), root.get("inputQTY")));
					}
				}
				//输入量大于0
				if(StringUtils.isNotBlank(param.getInputQTY())){
					if(StringUtils.equalsIgnoreCase(param.getInputQTY(), "大于0")){
						predicatesList.add(cb.ge(root.get("inputQTY"), 1));
					}
				}
				
				if (param.getBeginOfCreateTime()==null) {
					param.setBeginOfCreateTime("1900-1-1 00:00:00");
				}
				
				DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				try {
					Date beginDate = sdf.parse(param.getBeginOfCreateTime());
					predicatesList.add(cb.greaterThan(root.get("createTime"), beginDate));
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				if (param.getEndOfCreateTime()==null) {
					param.setEndOfCreateTime("2999-01-01 00:00:00");
				}
				
				try {
					Date endDate = sdf.parse(param.getEndOfCreateTime());
					predicatesList.add(cb.lessThan(root.get("createTime"), endDate));
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				query.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
				return null;
			}
		};

		return interfaceExecutionResultRepository.findAll(spec, pageable);
	}
	/**
	 * 查询执行中的接口
	 * @param param 类型:InterfaceExecutionResultParam
	 * @param pageable 类型：Pageable
	 * @return 带参数条件下的执行中接口
	 */
	@RequestMapping("/search/runningInterface")
	@RequiresPermissions(value={"implementationInterfaceQuery:view"})
	public Page<InterfaceExecutionResult> runningInterface(InterfaceExecutionResultParam param, Pageable pageable) {

		Specification<InterfaceExecutionResult> spec = new Specification<InterfaceExecutionResult>() {
			@Override
			public Predicate toPredicate(Root<InterfaceExecutionResult> root, CriteriaQuery<?> query,
					CriteriaBuilder cb) {
				List<Predicate> predicatesList = new ArrayList<>();

				if (StringUtils.isNotBlank(param.getInterfaceName())) {
					predicatesList.add(cb.like(root.get("interfaceName"), '%' + param.getInterfaceName() + "%"));
				}
				if (StringUtils.isNoneBlank(param.getFieldName())) {
					predicatesList.add(cb.equal(root.get("fieldName"), param.getFieldName()));
				}
				if (StringUtils.isNoneBlank(param.getFieldSystemName())) {
					predicatesList.add(cb.equal(root.get("fieldSystemName"), param.getFieldSystemName()));
				}else{
					Path<String> pathOwnerFieldSystemId = root.get("fieldSystemId");
					// 默认查当前登录用户所管理的领域系统
					Collection<String> fieldSystemIds = userSessionService.findFieldSystemIdsOfCurrentAuthenticatedUserCanManage();
					if(!CollectionUtils.isEmpty(fieldSystemIds)){
						predicatesList.add(pathOwnerFieldSystemId.in(fieldSystemIds));
					}else {
						predicatesList.add(cb.notEqual(cb.literal(1), 1));
					}
				}
				predicatesList.add(cb.equal(root.get("runResult"), InterfaceRunResult.Running.ValueCode));
				if (StringUtils.isNotBlank(param.getScheduleName())) {
					predicatesList.add(cb.equal(root.get("scheduleName"), param.getScheduleName()));
				}
				
				if (param.getBeginOfCreateTime()==null) {
					param.setBeginOfCreateTime("1900-1-1 00:00:00");
				}
				
				DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				try {
					Date beginDate = sdf.parse(param.getBeginOfCreateTime());
					predicatesList.add(cb.greaterThan(root.get("createTime"), beginDate));
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				if (param.getEndOfCreateTime()==null) {
					param.setEndOfCreateTime("2999-01-01 00:00:00");
				}
				
				try {
					Date endDate = sdf.parse(param.getEndOfCreateTime());
					predicatesList.add(cb.lessThan(root.get("createTime"), endDate));
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				query.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
				return null;
			}
		};

		return interfaceExecutionResultRepository.findAll(spec, pageable);
	}
	/**
	 * 查询所有失败的接口
	 * @param param 类型:InterfaceExecutionResultParam
	 * @param pageable 类型：Pageable
	 * @return 带参数条件下的失败接口
	 */
	@RequestMapping("/search/faildInterface")
	public Page<InterfaceExecutionResult> faildInterface(InterfaceExecutionResultParam param, Pageable pageable) {

		Specification<InterfaceExecutionResult> spec = new Specification<InterfaceExecutionResult>() {
			@Override
			public Predicate toPredicate(Root<InterfaceExecutionResult> root, CriteriaQuery<?> query,
					CriteriaBuilder cb) {
				List<Predicate> predicatesList = new ArrayList<>();

				if (StringUtils.isNotBlank(param.getInterfaceName())) {
					predicatesList.add(cb.like(root.get("interfaceName"), '%' + param.getInterfaceName() + "%"));
				}
				if (StringUtils.isNoneBlank(param.getFieldName())) {
					predicatesList.add(cb.equal(root.get("fieldName"), param.getFieldName()));
				}
				if (StringUtils.isNoneBlank(param.getFieldSystemName())) {
					predicatesList.add(cb.equal(root.get("fieldSystemName"), param.getFieldSystemName()));
				}else{
					Path<String> pathOwnerFieldSystemId = root.get("fieldSystemId");
					// 默认查当前登录用户所管理的领域系统
					Collection<String> fieldSystemIds = userSessionService.findFieldSystemIdsOfCurrentAuthenticatedUserCanManage();
					if(!CollectionUtils.isEmpty(fieldSystemIds)){
						predicatesList.add(pathOwnerFieldSystemId.in(fieldSystemIds));
					}else {
						predicatesList.add(cb.notEqual(cb.literal(1), 1));
					}
				}
				predicatesList.add(cb.equal(root.get("runResult"), InterfaceRunResult.Faild.ValueCode));
				if (StringUtils.isNotBlank(param.getScheduleName())) {
					predicatesList.add(cb.equal(root.get("scheduleName"), param.getScheduleName()));
				}
				if (param.getBeginOfCreateTime()==null) {
					param.setBeginOfCreateTime("1900-1-1 00:00:00");
				}
				
				DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				try {
					Date beginDate = sdf.parse(param.getBeginOfCreateTime());
					predicatesList.add(cb.greaterThan(root.get("createTime"), beginDate));
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				if (param.getEndOfCreateTime()==null) {
					param.setEndOfCreateTime("2999-01-01 00:00:00");
				}
				
				try {
					Date endDate = sdf.parse(param.getEndOfCreateTime());
					predicatesList.add(cb.lessThan(root.get("createTime"), endDate));
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				query.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
				return null;
			}
		};

		return interfaceExecutionResultRepository.findAll(spec, pageable);
	}
	/**
	 * 成功的接口数
	 * @param field 类型:String 
	 * @param system 类型:String
	 * @param beginOfCreateTime 类型：Date
	 * @param endOfCreateTime 类型：Date
	 * @return 成功的接口数
	 */
	// 成功统计
	private List<Tuple> successStatistics(String field, String system, Date beginOfCreateTime, Date endOfCreateTime) {
		CriteriaBuilder cb = entityManager.getCriteriaBuilder();
		CriteriaQuery<Tuple> cq = cb.createTupleQuery();

		// 构建FROM
		Root<InterfaceExecutionResult> root = cq.from(InterfaceExecutionResult.class);

		// 构建WHERE部分
		List<Predicate> predicatesList = new ArrayList<>();
		if (StringUtils.isNotBlank(field)) {
			predicatesList.add(cb.equal(root.get("fieldName"), field));
		}
		if (StringUtils.isNotBlank(system)) {
			predicatesList.add(cb.equal(root.get("fieldSystemName"), system));
		}else{
			Path<String> pathOwnerFieldSystemId = root.get("fieldSystemId");
			// 默认查当前登录用户所管理的领域系统
			Collection<String> fieldSystemIds = userSessionService.findFieldSystemIdsOfCurrentAuthenticatedUserCanManage();
			if(!CollectionUtils.isEmpty(fieldSystemIds)){
				predicatesList.add(pathOwnerFieldSystemId.in(fieldSystemIds));
			}else {
				predicatesList.add(cb.notEqual(cb.literal(1), 1));
			}
		}
		DynaBean fixedDates = DateUtil.fixBeginTimeAndEndTime(beginOfCreateTime, endOfCreateTime);
		Date fixedBeginTime = (Date) fixedDates.get("begin");
		Date fixedEndTime = (Date) fixedDates.get("end");
		Path<Date> pathDate = root.get("runBeginTime");
		predicatesList.add(cb.or(cb.isNull(pathDate), cb.between(pathDate, fixedBeginTime, fixedEndTime)));
		predicatesList.add(cb.equal(root.get("runResult"), InterfaceRunResult.Success.ValueCode));
		cq.where(predicatesList.toArray(new Predicate[predicatesList.size()]));

		// 构建GROUP BY部分
		cq.groupBy(root.get("fieldName"), root.get("fieldSystemName"));

		// 构建SELECT部分
		cq.multiselect(root.get("fieldName").alias("fieldName"), root.get("fieldSystemName").alias("fieldSystemName"),
				cb.count(root).alias("successAmount"));
		// 执行查询
		TypedQuery<Tuple> q = entityManager.createQuery(cq);
		List<Tuple> queryResult = q.getResultList();
		return queryResult;
	}
	/**
	 * 失败的接口数
	 * @param field 类型:String 
	 * @param system 类型:String
	 * @param beginOfCreateTime 类型：Date
	 * @param endOfCreateTime 类型：Date
	 * @return 失败的接口数
	 */
	// 失败统计
	private List<Tuple> faultStatistics(String field, String system, Date beginOfCreateTime, Date endOfCreateTime) {
		CriteriaBuilder cb = entityManager.getCriteriaBuilder();
		CriteriaQuery<Tuple> cq = cb.createTupleQuery();

		// 构建FROM
		Root<InterfaceExecutionResult> root = cq.from(InterfaceExecutionResult.class);

		// 构建WHERE部分
		List<Predicate> predicatesList = new ArrayList<>();
		if (StringUtils.isNotBlank(field)) {
			predicatesList.add(cb.equal(root.get("fieldName"), field));
		}
		if (StringUtils.isNotBlank(system)) {
			predicatesList.add(cb.equal(root.get("fieldSystemName"), system));
		}else{
			Path<String> pathOwnerFieldSystemId = root.get("fieldSystemId");
			// 默认查当前登录用户所管理的领域系统
			Collection<String> fieldSystemIds = userSessionService.findFieldSystemIdsOfCurrentAuthenticatedUserCanManage();
			if(!CollectionUtils.isEmpty(fieldSystemIds)){
				predicatesList.add(pathOwnerFieldSystemId.in(fieldSystemIds));
			}else {
				predicatesList.add(cb.notEqual(cb.literal(1), 1));
			}
		}
		DynaBean fixedDates = DateUtil.fixBeginTimeAndEndTime(beginOfCreateTime, endOfCreateTime);
		Date fixedBeginTime = (Date) fixedDates.get("begin");
		Date fixedEndTime = (Date) fixedDates.get("end");
		Path<Date> pathDate = root.get("runBeginTime");
		predicatesList.add(cb.or(cb.isNull(pathDate), cb.between(pathDate, fixedBeginTime, fixedEndTime)));
		predicatesList.add(cb.equal(root.get("runResult"), InterfaceRunResult.Faild.ValueCode));
		cq.where(predicatesList.toArray(new Predicate[predicatesList.size()]));

		// 构建GROUP BY部分
		cq.groupBy(root.get("fieldName"), root.get("fieldSystemName"));

		// 构建SELECT部分
		cq.multiselect(root.get("fieldName").alias("fieldName"), root.get("fieldSystemName").alias("fieldSystemName"),
				cb.count(root).alias("faultAmount"));
		// 执行查询
		TypedQuery<Tuple> q = entityManager.createQuery(cq);
		List<Tuple> queryResult = q.getResultList();
		return queryResult;
	}
	/**
	 * 成功和失败的接口数
	 * @param field 类型:String 
	 * @param system 类型:String
	 * @param beginOfCreateTime 类型：Date
	 * @param endOfCreateTime 类型：Date
	 * @return 成功和失败的接口数
	 */
	// 统计查询功能
	@RequestMapping(value = "/statistics/forInterfaceSummary", produces = "application/json")
//	@RequiresPermissions(value={"implementationInterfaceSummaryTable:view"})
	public String countByFieldAndSystem(String field, String system,
			@DateTimeFormat(pattern = Constants.DATETIME_PATTERN_1) Date beginOfCreateTime,
			@DateTimeFormat(pattern = Constants.DATETIME_PATTERN_1) Date endOfCreateTime) {

		List<Tuple> queryResult1 = successStatistics(field, system, beginOfCreateTime, endOfCreateTime);
		List<Tuple> queryResult2 = faultStatistics(field, system, beginOfCreateTime, endOfCreateTime);

		MultiKeyMap<String, JsonObject> mixResult = new MultiKeyMap<>();

		for (Tuple tuple : queryResult1) {
			String fieldname = tuple.get("fieldName", String.class);
			String fieldSystemName = tuple.get("fieldSystemName", String.class);
			Long successAmount = tuple.get("successAmount", Long.class);

			JsonObject jo = mixResult.get(fieldname, fieldSystemName);
			if (jo == null) {
				jo = new JsonObject();
				jo.addProperty("fieldName", fieldname);
				jo.addProperty("fieldSystemName", fieldSystemName);
				jo.addProperty("faultAmount", 0L);
			}
			jo.addProperty("successAmount", successAmount);
			mixResult.put(fieldname, fieldSystemName, jo);
		}
		for (Tuple tuple : queryResult2) {
			String fieldname = tuple.get("fieldName", String.class);
			String fieldSystemName = tuple.get("fieldSystemName", String.class);
			Long faultAmount = tuple.get("faultAmount", Long.class);

			JsonObject jo = mixResult.get(fieldname, fieldSystemName);
			if (jo == null) {
				jo = new JsonObject();
				jo.addProperty("fieldName", fieldname);
				jo.addProperty("fieldSystemName", fieldSystemName);
				jo.addProperty("successAmount", 0L);
			}
			jo.addProperty("faultAmount", faultAmount);
			mixResult.put(fieldname, fieldSystemName, jo);
		}

		NumberFormat numberFormat = NumberFormat.getPercentInstance();
		numberFormat.setMaximumFractionDigits(4);
		JsonArray jsonDatas = new JsonArray();
		for (JsonObject jo : mixResult.values()) {
			long successAmount = jo.get("successAmount").getAsLong();
			long faultAmount = jo.get("faultAmount").getAsLong();
			long totalAmount = successAmount + faultAmount;
			jo.addProperty("totalAmount", totalAmount);

			String successPercent = numberFormat.format((float) successAmount / totalAmount);

			jo.addProperty("successPercent", successPercent);

			jsonDatas.add(jo);
		}
		
		JsonObject jsonResult = new JsonObject();
		jsonResult.add("content", jsonDatas);
		return jsonResult.toString();
	}
	/**
	 * 查询日志
	 * @param id 类型:String
	 * @return 日志
	 */
	@RequestMapping(value = "/search/logs",produces = "application/json")
	public String checkLog(String id){
		InterfaceExecutionResult entity = interfaceExecutionResultRepository.findOne(InterfaceExecutionResult.idSpecification(id));
		String log = null;
		if(entity!=null){
			entity.getLogField();
			String separator = System.getProperty("line.separator");
			log = StringUtils.replace(entity.getLogField(),separator, "<br>");
		}
		JsonObject jo = new JsonObject();
		jo.addProperty("logField", log);
		return jo.toString();
	}
	//时候保存输入输出量为0且成功的数据
	@RequestMapping(value = "/change/forLog",produces = "application/json")
	public String changeChange(String changeInfo){
		boolean result = Constants.changeResult;
		ParamSetting paramsetting = paramSettingRepository.findByParamName("作业日志设置");
		if(StringUtils.equals(changeInfo, "不保存")){
			Constants.changeResult = true;
			paramsetting.setParamValue("true");
			result = Constants.changeResult;
		}else{
			Constants.changeResult = false;
			paramsetting.setParamValue("false");
			result = Constants.changeResult;
		}
		paramSettingRepository.save(paramsetting);
		JsonObject jo = new JsonObject();
		jo.addProperty("logField", result);
		return jo.toString();
	}
	//获取状态
	@RequestMapping(value = "/getchange/forLog",produces = "application/json")
	public String getChangeInfo(){
		boolean result = Constants.changeResult;
		ParamSetting paramsetting = paramSettingRepository.findByParamName("作业日志设置");
		if(StringUtils.equals(paramsetting.getParamValue(),"true")){
			result  = true;
		}else{
			result = false;
		}
		JsonObject jo = new JsonObject();
		jo.addProperty("logField", result);
		return jo.toString();
	}
	
	
	
}
